#pragma once

#include "log.hpp"
#include "Socket.hpp"
#include "ServerCal.hpp"
#include <signal.h>
#include <functional>
#include <string>
using func_t = std::function<std::string(std::string &package)>;
class TcpServer
{
public:
    TcpServer(uint16_t port, func_t callback)
        : port_(port), callback_(callback)
    {
    }
    bool InitServer()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();
        lg(Info, "服务器初始化完成...");
        return true;
    }
    void Start()
    {
        signal(SIGCHLD, SIG_IGN);
        signal(SIGPIPE, SIG_IGN); // 忽略tcp链接终止的信号
        while (true)
        {
            std::string clientip;
            uint16_t clientport;
            int sockfd = listensock_.Accept(&clientip, &clientport); // 返回的这个sockfd才是传输数据用的文件描述符
            if (sockfd < 0)
                continue;

            lg(Info, "接收到一个新的连接请求,sockfd:%d,clientip: %s,clientport: %d", sockfd, clientip.c_str(), clientport);
            // 提供服务
            if (fork() == 0) // 子进程
            {
                listensock_.Close(); // 子进程关闭监听文件描述符
                std::string inbuffer_stream;
                // 数据计算
                while (true)
                {
                    char buffer[128];                                 // 存数据用的变量
                    ssize_t n = read(sockfd, buffer, sizeof(buffer)); // 从网络中读取数据，存到buffer里
                    if (n > 0)
                    {
                        buffer[n] = 0;             // 结尾带上\0
                        inbuffer_stream += buffer; // 再存到inbuffer_stream里

                        lg(Debug, "debug: %s", inbuffer_stream.c_str());

                        while (true)
                        {
                            std::string info = callback_(inbuffer_stream); // 回调函数检查报文是否完整，不完整，info收到的就是空串
                            if (info.empty())
                                continue; // 说明收到的是空串，不遵守协议

                            // 向客户端发送回信息
                            write(sockfd, info.c_str(), info.size());
                        }
                    }
                    else if (n == 0)
                        break; // 说明读取出错，直接退
                    else
                        break;
                }
                exit(0); // 子进程直接退出
            }
            close(sockfd); // 父进程关闭套接字文件描述符
        }
    }

private:
    uint16_t port_;
    Sock listensock_;
    func_t callback_;
};